package com.ushine.web.component.lock;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.service.spi.ServiceException;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Author: yls
 * @Date 2022/4/6 10:30
 * @Description: 锁对象测试
 * @Version 1.0
 **/
@Slf4j
public class LockTest {
    /**
     * 实例化锁对象
     */
    private static final Lock LOCK = new ReentrantLock();

    /**
     * 功能描述:
     * 〈 涉及统计值的处理方法一 〉
     *
     * @return : void
     * @author : yls
     * @date : 2022/4/6 10:33
     */
    public void lockFirst(AtomicInteger count) throws InterruptedException {
        LOCK.lockInterruptibly();
        try {

            // 锁定
//            LOCK.lock();

            // 业务处理（涉及线程安全的逻辑处理）
            count.set(count.get() + 1);
            log.info("当前线程名称：{}，当前的统计值：{}", Thread.currentThread().getName(), count);
            System.out.println("当前线程名称：" + Thread.currentThread().getName() + "，当前的统计值：" + count);

        } finally {
            //解锁，流程处理完一定要解锁，不然容易出现死锁
            LOCK.unlock();
        }
    }

    /**
     * 功能描述:
     * 〈 涉及统计值的处理方法二 〉
     *
     * @param count 数据值
     * @return : void
     * @author : yls
     * @date : 2022/4/6 10:40
     */
    public void lockSecond(AtomicInteger count) throws InterruptedException {
        LOCK.lockInterruptibly();
        try {
            // 锁定
//            LOCK.lock();
            // 业务处理（涉及线程安全的逻辑处理）
            count.set(count.get() + 1);
            log.info("当前线程名称：{}，当前的统计值：{}", Thread.currentThread().getName(), count);
            System.out.println("当前线程名称：" + Thread.currentThread().getName() + "，当前的统计值：" + count);

        } finally {
            //解锁，流程处理完一定要解锁，不然容易出现死锁
            LOCK.unlock();
        }
    }


    /**
     * 功能描述:
     * 〈 涉及统计值的处理方法三 〉
     *
     * @param count 数据值
     * @return : void
     * @author : yls
     * @date : 2022/4/6 10:40
     */
    public void lockThree(AtomicInteger count) {
        if (LOCK.tryLock()) {
            try {
                // 业务处理（涉及线程安全的逻辑处理）
                count.set(count.get() + 1);
                log.info("当前线程名称：{}，当前的统计值：{}", Thread.currentThread().getName(), count);
                System.out.println("当前线程名称：" + Thread.currentThread().getName() + "，当前的统计值：" + count);

            } finally {
                //解锁，流程处理完一定要解锁，不然容易出现死锁
                LOCK.unlock();
            }
        } else {
            System.out.println("当前系统正忙，请稍后再尝试！");
        }

    }


    /**
     * 功能描述:
     * 〈 涉及统计值的处理方法三 〉
     *
     * @param count 数据值
     * @return : void
     * @author : yls
     * @date : 2022/4/6 10:40
     */
    public void lockFour(AtomicInteger count) {
        try {
            if (LOCK.tryLock(1, TimeUnit.SECONDS)) {
                // 业务处理（涉及线程安全的逻辑处理）
                count.set(count.get() + 1);
                log.info("当前线程名称：{}，当前的统计值：{}", Thread.currentThread().getName(), count);
                System.out.println("当前线程名称：" + Thread.currentThread().getName() + "，当前的统计值：" + count);

            } else {
                throw new ServiceException("当前系统正忙，请稍后再尝试！");
            }

        } catch (InterruptedException e) {
            System.out.println("未获取到锁，请稍后重试！");
            Thread.currentThread().interrupt();
        } finally {
            //解锁，流程处理完一定要解锁，不然容易出现死锁
            LOCK.unlock();
        }
    }


    public static void main(String[] args) {
        LockTest lockTest = new LockTest();
        // 多线程提交测试
        // 使用 ThreadFactoryBuilder 创建自定义线程名称的 ThreadFactory
        ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
                .setNameFormat("hyn-demo-pool-%d").build();
        // 创建线程池，其中任务队列需要结合实际情况设置合理的容量
        ThreadPoolExecutor executor = new ThreadPoolExecutor(1000,
                1000,
                0L,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(1024),
                namedThreadFactory,
                new ThreadPoolExecutor.AbortPolicy());
        AtomicInteger count = new AtomicInteger(100);
        // 新建 100 个任务，
        for (int i = 0; i < 100; i++) {
            executor.execute(() -> {
                try {
                    lockTest.lockFirst(count);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    Thread.currentThread().interrupt();
                }
            });
        }

        // 新建 100 个任务
        for (int i = 0; i < 100; i++) {
            executor.execute(() -> {
                try {
                    lockTest.lockSecond(count);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    Thread.currentThread().interrupt();
                }
            });
        }

        // 新建 100 个任务
        for (int i = 0; i < 100; i++) {
            executor.execute(() -> {
                lockTest.lockThree(count);
            });
        }

        // 新建 100 个任务
        for (int i = 0; i < 100; i++) {
            executor.execute(() -> {
                lockTest.lockFour(count);
            });
        }
    }

}
